package cn.js.sangu.unitStore.service;

import java.io.File;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.js.sangu.unitStore.common.constant.SysInfo;
import cn.js.sangu.unitStore.common.exception.ServiceException;
import cn.js.sangu.unitStore.dto.FileListDTO;
import cn.js.sangu.unitStore.dto.PartAttributeDTO;
import cn.js.sangu.unitStore.dto.UtilsDTO;
import cn.js.sangu.unitStore.entity.ExcelData;
import cn.js.sangu.unitStore.entity.FileNas;
import cn.js.sangu.unitStore.entity.UtilsEntity;
import cn.js.sangu.unitStore.mapper.UtilsMapper;
import cn.js.sangu.unitStore.service.async.UtilsAsyncService;
import cn.js.sangu.unitStore.service.process.ExcelProcessService;
import cn.js.sangu.unitStore.utils.LinsUtil;
import cn.js.sangu.unitStore.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 说明：常用工具处理服务
 * 作者：linshuo
 */
@Slf4j
@Service
@EnableAsync
public class UtilsService extends ServiceImpl<UtilsMapper, UtilsEntity> {

    static final String ROOT_PATH = System.getProperty("user.dir") + File.separator + "files";
    static String today = DateUtil.today();
    static String folderRootPath = ROOT_PATH + File.separator + today + File.separator;

    private final ExcelProcessService excelProcessService;
    private final UtilsAsyncService utilsAsyncService;

    public UtilsService(ExcelProcessService excelProcessService, UtilsAsyncService utilsAsyncService) {
        this.excelProcessService = excelProcessService;
        this.utilsAsyncService = utilsAsyncService;
    }

    /**
     * 保存工具任务记录
     * 
     * @param dto
     * @return
     * @throws JsonProcessingException
     */
    public UtilsEntity saveInfo(UtilsDTO dto) throws JsonProcessingException {
        UtilsEntity utilsEntity = spliceAttachInfo(dto);
        utilsEntity.setCreator(Objects.requireNonNull(TokenUtils.getCurrentUser()).getId());
        // 设置初始状态为正在加工
        utilsEntity.setState(SysInfo.ProcessStatusProcessing); // 0: 正在加工，1: 加工成功，2: 加工失败
        // 保存任务记录
        if (!super.save(utilsEntity)) {
            throw new ServiceException("Utils记录保存失败！请联系管理员");
        }

        // 开始执行加工，需要获取加工结果，同步逻辑清晰一些
        // FileNas fileNas = executiveProcess(utilsEntity);
        // 加工结果文件地址暂时保存到类型里
        // utilsEntity.setAttachType(fileNas.getFilePath());

        // 将上述同步逻辑改为异步
        long startTime = System.currentTimeMillis();
        log.info("====> {}线程：开始调用异步任务 <====", Thread.currentThread().getName());
        // 在进入异步方法前获取用户 ID
        Long userId = null;
        try {
            userId = TokenUtils.getCurrentUser() != null ? Long.valueOf(TokenUtils.getCurrentUser().getId()) : null;
        } catch (Exception e) {
            log.error("获取当前用户 ID 时发生异常", e);
        }
        utilsAsyncService.executiveProcess(utilsEntity, dto.getAutoCode(), userId);
        long end = System.currentTimeMillis();
        log.info("====> {}线程：调用异步任务结束，耗时{}毫秒", Thread.currentThread().getName(), end - startTime);

        // utilsEntity.setReceiptState(SysInfo.UtilProcessing); //加工状态：0正在加工，1加工成功，2加工失败
        // if (!super.save(utilsEntity)){
        // throw new ServiceException("Utils记录保存失败！请联系管理员");
        // }
        // //保存文件记录 2025/1/23：转移到加工方法内，外面只负责关于Util的业务
        // if (!fileService.save(fileNas)){
        // throw new ServiceException("Utils-文件记录保存失败！请联系管理员");
        // }

        // 主动通知结果

        // 返回加工结果
        return utilsEntity;
    }

    private UtilsEntity spliceAttachInfo(UtilsDTO dto) {
        UtilsEntity entity = convertDTOToEntity(dto);
        // 临时存
        List<String> attachNameList = new LinkedList<>();
        List<Integer> ids = new LinkedList<>();
        // 工单的多个附件
        List<FileListDTO> list = entity.getFileList();
        if (null != list) {
            for (FileListDTO fileList : list) {
                attachNameList.add(fileList.getName());
                // 取出原本的File对象
                FileNas fileNas = BeanUtil.toBean(fileList.getResponse().getData(), FileNas.class);
                ids.add(fileNas.getId());
            }
            entity.setAttachName(list.size() > 0 ? attachNameList.toString() : "");
            entity.setAttachIds(ids.toString());
            entity.setAttachCount(list.size()); // 附件个数

            // dto.setFileList(dto.getFileList());
            entity.setFileListJson(new ObjectMapper().valueToTree(entity.getFileList()));
        }
        this.keywordReplace(entity);
        return entity;
    }

    public UtilsEntity updateInfo(UtilsDTO dto) {
        UtilsEntity utilsEntity = spliceAttachInfo(dto);
        // 设置修改人名称
        utilsEntity.setModifier(Objects.requireNonNull(TokenUtils.getCurrentUser()).getId());
        // 补充接收信息
        addReceiveInfo(dto);
        if (!super.updateById(dto)) {
            throw new ServiceException("更新失败！请联系管理员");
        }
        return utilsEntity;
    }

    private void keywordReplace(UtilsEntity dto) {
        dto.setWorkName(LinsUtil.keywordReplace(dto.getWorkName(), null, null));
        dto.setWorkDescription(LinsUtil.keywordReplace(dto.getWorkDescription(), null, null));
    }

    private void addReceiveInfo(UtilsEntity dto) {
        if (null == dto.getReceiptStateLast())
            dto.setReceiptStateLast(0);
        if (dto.getReceiptStateLast() == 0 && dto.getState() == 1) {
            // 状态从未接收 改为 确认接收，记录接收时间
            dto.setReceiptTime(new Date());
        }
    }

    /**
     * 将 UtilsDTO 转换为 UtilsEntity
     * 
     * @param dto UtilsDTO 对象
     * @return UtilsEntity 对象
     */
    private UtilsEntity convertDTOToEntity(UtilsDTO dto) {
        UtilsEntity entity = new UtilsEntity();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }

    @Async("taskExecutor") // 异步方法
    public void asyncTask() {
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        log.info("{} ：UtilsService.asyncTask 异步方法用时{}毫秒", Thread.currentThread().getName(), end - start);
    }

    public String test() {
        return excelProcessService.test();
    }

    // public String autocode(PartAttributeDTO dto) {
    // ExcelData data = new ExcelData();
    // data.setTuhao(dto.getTuhao());
    // data.setCailiao(dto.getCailiao());
    // data.setGuige(dto.getGuige());
    // data.setLeibie(dto.getLeibie());
    // data.setName(dto.getName());

    // return excelProcessService.autocode(data);
    // }

    // public PartAttributeDTO parseAttributes(String code) {
    // return excelProcessService.parseAttributes(code);
    // }

    // public void clearCount() {
    // excelProcessService.clearCount();
    // }

    /**
     * 测试websocket工具
     * 
     * @param uid
     */
    public void testWs(String uid) {
        utilsAsyncService.testWs(uid);
    }

}
